package com.ttx.single.lab.service.transform;

import com.ttx.single.lab.mapper.OrderItemMapper;
import com.ttx.single.lab.mapper.OrderMapper;
import com.ttx.single.lab.model.bo.OrderBO;
import com.ttx.single.lab.model.dataobject.OrderDO;
import com.ttx.single.lab.model.dataobject.OrderItemDO;
import com.ttx.single.lab.model.dto.PlaceOrderDto;
import com.ttx.single.lab.service.CommonDoubleWriteOrderService;
import com.ttx.single.lab.service.OrderService;
import com.ttx.single.lab.service.sharding.OrderServiceShardingImpl;
import com.ttx.single.lab.util.MockUtil;
import com.ttx.suite.web.model.bo.PageBO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 3
 * # 1 使用uid的初始下单  2 下单双写，以单库读写为主  3  下单双写， 以分库读写为主 4 下单只写在分库
 * @author TimFruit
 * @date 20-4-12 上午8:58
 */
@Service
public class OrderServiceTransformStep3 implements OrderService {

    //单库
    @Autowired
    @Qualifier("singleOrderMapper")
    OrderMapper singleOrderMapper;
    @Autowired
    @Qualifier("singleOrderItemMapper")
    OrderItemMapper singleOrderItemMapper;


    //分库分表
    @Autowired
    @Qualifier("shardingOrderMapper")
    OrderMapper shardingOrderMapper;
    @Autowired
    @Qualifier("shardingOrderItemMapper")
    OrderItemMapper shardingOrderItemMapper;

    @Autowired
    CommonDoubleWriteOrderService doubleWriteOrderService;
    @Autowired
    OrderServiceShardingImpl orderServiceSharding;


    //warning 单库  与  分库 的分布式事务


    //以分库分表事务为主
    @Override
    public void placeOrder(PlaceOrderDto orderDto) {
        //3 下单双写， 以分库读写为主
        OrderDO orderDO= doubleWriteOrderService.generateOrderId(orderDto);
        List<OrderItemDO> orderItemDOS= doubleWriteOrderService.generateOrderItemIds(orderDto.getItemDtos(),orderDO.getOrderId());


        //以分库分表事务为主, 分库事务执行失败，单库事务必定未执行
        //单库事务执行失败， 分库事务必定执行成功
        //通过数据同步 (分库 -> 单库) , 可以将差异补平

        //从本步骤(3) 回退到 步骤(2) 后， 需要重新数据同步(单库 -> 分库) ，



        doubleWriteOrderService.shardingPlaceOrder(orderDO, orderItemDOS);

        doubleWriteOrderService.singlePlaceOrder(orderDO, orderItemDOS);




        //模拟异常
        MockUtil.randomException();

        //保存order_id 和 userid的映射关系
        doubleWriteOrderService.insertOrderMapping(orderDO.getOrderId(), orderDO.getUserId());


        //模拟异常
        MockUtil.randomException();

    }





    // --------- 以分库读为主


    @Override
    public PageBO<OrderBO> listUserOrderPage(Long userId, Integer pageNum, Integer pageSize) {
        //以分库分表读
        return orderServiceSharding.listUserOrderPage(userId, pageNum, pageSize);
    }

    @Override
    public OrderBO selectOrder(Long orderId) {
        //以分库分表读
        return orderServiceSharding.selectOrder(orderId);
    }


    //--------- 双写 以分库为主
    @Override
    public void cancelOrder(Long orderId, Integer userId) {
        Date date=new Date();
        doubleWriteOrderService.singleCancelOrder(orderId,userId,date);
        doubleWriteOrderService.shardingCancelOrder(orderId, userId,date);
    }
}
